package so.sao.code.service.infrastructure.utils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @ClassName: EncryptUtil
 * @Description: 加密工具类
 * @author liuzelei
 * @date 2017年6月14日 下午10:14:01
 */
public class EncryptUtil {
	private final static Logger LOGGER = LoggerFactory.getLogger(EncryptUtil.class);

	/**
	 * 
	 * @Title: encryptData
	 * @Description: TODO(对字字符串加密) @return byte[]
	 * @date 2017年6月16日 下午7:17:36
	 * @param encryptdata
	 * @param keys
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptData(String encryptdata, String keys) throws Exception {
		final SecureRandom sr = new SecureRandom();

		final byte[] rawKeyData = keys.getBytes("utf-8");
		final DESKeySpec dks = new DESKeySpec(rawKeyData);

		final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		final SecretKey key = keyFactory.generateSecret(dks);
		final Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, key, sr);

		return cipher.doFinal(encryptdata.getBytes("UTF-8"));
	}

	public static String decryptData(byte[] decryptdata, String keys) throws Exception {

		SecureRandom sr = new SecureRandom();

		byte[] rawKeyData = keys.getBytes("utf-8");
		DESKeySpec dks = new DESKeySpec(rawKeyData);

		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey key = keyFactory.generateSecret(dks);

		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, key, sr);

		return new String(cipher.doFinal(decryptdata), "UTF-8");
	}

	/**
	 * 
	 * @Title: encryptByteData
	 * @Description: TODO(对字节数组加密) @return byte[]
	 * @date 2017年6月16日 下午7:16:18
	 * @param encryptdata
	 * @param keys
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByteData(byte[] encryptdata, String keys) throws Exception {
		SecureRandom sr = new SecureRandom();

		byte[] rawKeyData = keys.getBytes("utf-8");
		DESKeySpec dks = new DESKeySpec(rawKeyData);

		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey key = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, key, sr);

		return cipher.doFinal(encryptdata);
	}

	public static byte[] decryptByteData(byte[] decryptdata, String keys) throws Exception {

		SecureRandom sr = new SecureRandom();

		byte[] rawKeyData = keys.getBytes("utf-8");
		DESKeySpec dks = new DESKeySpec(rawKeyData);

		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey key = keyFactory.generateSecret(dks);

		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, key, sr);

		return cipher.doFinal(decryptdata);
	}

	/**
	 * Encode a string using Base64 encoding. Used when storing passwords as
	 * cookies.
	 * 
	 * This is weak encoding in that anyone can use the decodeString routine to
	 * reverse the encoding.
	 * 
	 * @param str
	 * @return String
	 */
	public static String encodeString(String str) {
		sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
		try {
			return encoder.encodeBuffer(str.getBytes("utf-8")).trim();
		} catch (Exception e) {
			LOGGER.error("", e);
			return null;
		}
	}

	public static String encodeString(byte[] bdata) {
		sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
		try {
			return encoder.encodeBuffer(bdata).trim();
		} catch (Exception e) {
			LOGGER.error("", e);
			return null;
		}
	}

	/**
	 * Decode a string using Base64 encoding.
	 * 
	 * @param str
	 * @return String
	 */
	public static byte[] decodeString(String str) {
		sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
		try {
			return dec.decodeBuffer(str);
		} catch (IOException io) {
			LOGGER.error("", io);
			return null;
		}
	}

	/**
	 * @Title: decryptFile
	 * @return String
	 * @param filePath
	 * @param keys
	 * @param rnFilePath
	 * @return
	 * @throws Exception
	 */
	public static String decryptFile(String filePath, String keys, String rnFilePath) throws Exception {
		FileInputStream in = new FileInputStream(filePath);
		int i = in.available();
		byte[] b1 = new byte[i];
		in.read(b1);
		in.close();
		// shixy-删除加密后的文件
		Files.delete(Paths.get(filePath));

		byte[] b2 = decryptByteData(b1, keys);

		FileOutputStream out = new FileOutputStream(rnFilePath);
		out.write(b2);
		out.close();
		return rnFilePath;
	}

	/**
	 * @Title: encryptFile
	 * @Description:
	 * @return String
	 * @param filePath
	 * @param keys
	 * @return
	 * @throws Exception
	 */
	public static String encryptFile(String filePath, String keys) throws Exception {
		FileInputStream in = new FileInputStream(filePath);
		int i = in.available();
		byte[] b1 = new byte[i];
		in.read(b1);
		in.close();
		byte[] b2 = encryptByteData(b1, keys);

		String rnFilePath = filePath + ".des";
		FileOutputStream out = new FileOutputStream(rnFilePath);
		out.write(b2);
		out.close();
		return rnFilePath;
	}

	/**
	 * @Title: encrypt
	 * @Description: 加密
	 * @return String
	 * @author liuzelei
	 * @date 2017年7月21日 下午5:47:58
	 * @param msg
	 * @param password
	 * @return
	 */
	public static String encrypt(String msg, String password) {
		String encryptedData = null;
		try {
			// DES算法要求有一个可信任的随机数源
			SecureRandom sr = new SecureRandom();
			DESKeySpec deskey = new DESKeySpec(password.getBytes());
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey key = keyFactory.generateSecret(deskey);
			// 加密对象
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, key, sr);
			// 加密，并把字节数组编码成字符串
			encryptedData = new sun.misc.BASE64Encoder().encode(cipher.doFinal(msg.getBytes("utf8")));
		} catch (Exception e) {
			// log.error("加密错误，错误信息：", e);
			throw new RuntimeException("加密错误，错误信息：", e);
		}
		return encryptedData;
	}

	/**
	 * @Title: decrypt
	 * @Description: 解密
	 * @return String
	 * @date 2017年7月21日 下午5:48:34
	 * @param msg
	 * @param password
	 * @return
	 * @throws Exception
	 */
	public static String decrypt(String msg, String password) throws Exception {
		String decryptedData = null;
		try {
			// DES算法要求有一个可信任的随机数源
			SecureRandom sr = new SecureRandom();
			DESKeySpec deskey = new DESKeySpec(password.getBytes());
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey key = keyFactory.generateSecret(deskey);
			// 解密对象
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.DECRYPT_MODE, key, sr);
			// 把字符串解码为字节数组，并解密
			decryptedData = new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(msg)), "utf8");
		} catch (Exception e) {
			// log.error("解密错误，错误信息：", e);
			throw new RuntimeException("解密错误，错误信息：", e);
		}
		return decryptedData;
	}

}
